#!/usr/bin/env ruby

require 'rubygems'
require 'rake'
require 'rake/clean'
require 'pathname'

TRUNK = Dir.pwd + '/trunk'
BRANCH = Dir.pwd + 'branches/' + %x{hostname -s}.strip
HAS_BRANCH = File.exist? BRANCH

EMACS_ROOT = "#{TRUNK}/emacs"
EMACS_INI = "#{EMACS_ROOT}/ini"
EMACS_PACKAGES = "#{EMACS_ROOT}/packages"
EMACS_CACHE = "#{EMACS_ROOT}/tmp/cache"

Struct.new('EmacsPackage', :name, :version, :include_dirs)
PACKAGES = Hash.new

PKG_FILES = FileList["#{EMACS_PACKAGES}/pkg-*.yml"]
ELC_FILES = FileList['**/*.elc']

CLEAN.include('**/.*.bak', '**/*.gz')

CLOBBER.include(ELC_FILES, FileList["#{EMACS_PACKAGES}/*/"].exclude('elib-1.0'))

directory EMACS_CACHE

task :default => :install

desc 'Install the config!'
task :install => [:clobber, :elc, :link]

desc 'Byte compile all elisp files'
task :elc => :elc_packages do
  el = FileList["#{EMACS_ROOT}/*.el"]
  el.include("#{BRANCH}/emacs/*.el") if HAS_BRANCH
  el.each do |el|
    sh %{ emacs -batch -f batch-byte-compile #{el} } do |ok, res|
      puts res if !ok
    end
  end
end

multitask :elc_packages => :get_packages do
  Dir["#{EMACS_PACKAGES}/*/"].each do |pkg|
    puts "byte compiling #{pkg}..."
    Dir.chdir pkg
    if File.exists? 'Makefile'
      sh %{ make } do |ok, res|
        puts res if !ok
      end
    else
      pkg_info = PACKAGES[pkg.pathmap('%f')]
      elisp = FileList['*.el']
      if !pkg_info.include_dirs.nil?
        pkg_info.include_dirs.each { |d| elisp.include("#{d}/*.el") }
      end

      elisp.each do |el|
        sh %{ emacs -batch -f batch-byte-compile #{el} } do |ok, res|
          puts res if !ok
        end
      end
    end
    Dir.chdir Rake.original_dir
  end
end

desc 'Download packages for emacs config'
multitask :get_packages do
  PKG_FILES.each do |pkg|
    pkg_info = YAML::load_file pkg
    ep = Struct::EmacsPackage.new(pkg_info['name'],
                                  pkg_info['version'],
                                  pkg_info['include_dirs'])

    puts "downloading #{ep.name} (#{ep.version}) => #{EMACS_PACKAGES}..."
    pkg_dir = "#{EMACS_PACKAGES}/#{ep.name}"
    if pkg_info['cmd'] == 'curl'
      sh %{ curl #{pkg_info['url']} -o #{ep.name}.tar.gz &&
            tar -zxf #{ep.name}.tar.gz -C #{EMACS_PACKAGES} }
      sh %{ mv #{pkg_dir}* #{pkg_dir} }
    else
      sh %{ svn checkout #{pkg_info['url']} #{pkg_dir} }
    end

    PACKAGES[ep.name] = ep
  end
end

desc 'Symlink dotfiles to home directory'
task :link => [:backup, :link_profile_local, :link_emacs_conf_dir] do
  if HAS_BRANCH
    puts 'has a branch'
    # merge filelists
  else
    FileList["#{TRUNK}/.[^.]*"].exclude('.profile_local').each do |df|
      dest_df = df.sub(TRUNK, ENV['HOME'])
      ln_sf(df, dest_df)
      puts "ln -s #{df} #{dest_df}"
    end
  end
end

# platform specific profile goodies
task :link_profile_local do
  if /(darwin|linux)/ =~ RUBY_PLATFORM
    ln_sf("#{TRUNK}/.profile_local/#{$1}", "#{ENV['HOME']}/.profile_local")
  end
end

# emacs conf dir's name is controlled through the root-directory var
task :link_emacs_conf_dir do
  FileList.new("#{TRUNK}/.emacs").egrep(/defvar root-directory/) do |fn, c, m|
    /user-login-name "(\S+)"/ =~ m
  end
  emacs_dirname = "#{ENV['HOME']}#{$1}"
  rm emacs_dirname if File.directory? emacs_dirname
  ln_sf(EMACS_ROOT, emacs_dirname)
  puts "ln -s #{EMACS_ROOT} #{emacs_dirname}"
  
  if HAS_BRANCH
    FileList["#{BRANCH}/emacs/**/*.el*"].each do |el|
      ln_sf(el, el.sub(BRANCH, TRUNK))
    end
  end
end

task :backup do
  if HAS_BRANCH
    # TODO: merge filelists
  else
    FileList["#{TRUNK}/.*"].each do |df|
      dest = df.sub(TRUNK, ENV['HOME'])
      backup = "#{df}.bak"
      if File.file? dest
        if File.symlink? dest
          dest_file = File.readlink(dest)
          path_to_dest = Pathname.new(dest_file)
          dest_file = "#{ENV['HOME']}/#{dest_file}" if !path_to_dest.absolute?
          cp(dest_file, backup)
        else
          cp(dest, backup)
        end
      end
    end
  end
end

desc "Look for TODO and FIXME tags in the config"
task :todo do
  FileList["#{EMACS_INI}/*.el", __FILE__].egrep(/(FIXME|TODO|TBD)/)
end
